#include "gbser.h"
#include "strptime.h"
#include "jeeps/gpsmath.h"
+#include "src/core/logging.h"
#include <ctype.h>
#include <math.h>
' $GPRMC - Recommended minimum specific GNSS Data
' $GPRMC,085721.194,A,5917.7210,N,01103.9227,E,21.42,50.33,300504,,*07
' 2 085721 Fix taken at 08:57:21 UTC
- ' 3 A Fix valid (this field reads V if fix is not valid)
+ ' 3 A Fix valid (this field reads V if fix is not valid)
' 4,5 5917.7210,N Latitude 59 deg 17.7210' N
' 6,7 01103.9227,E Longitude 11 deg 03.9227' E
- ' 8 21.42 Speed over ground (knots)
- ' 9 50.33 Course over ground (true)
- ' 10 300504 Date 30/05-2004
+ ' 8 21.42 Speed over ground (knots)
+ ' 9 50.33 Course over ground (true)
+ ' 10 300504 Date 30/05-2004
' 11 Empty field Magnetic variation
GSA - GPS DOP and active satellites
WAYPT_SET(waypt, geoidheight, geoidheight);
- waypt->sat = nsats;
+ waypt->sat = nsats;
- waypt->hdop = hdop;
+ waypt->hdop = hdop;
switch (fix) {
case 0:
// This can't have worked.
}
+// This function has had a hard life. It began as a moderately terrifying
+// bunch of nested sscanfs. In 2017, robertl replaced the scanf stuff with
+// a QString::split() to make it more tolerant of really empty fields from
+// certain GPS implementations, but didn't replace the (somewhat funky) back
+// half to match the parse. There are definitely some readibility issues
+// here.
+// The numbering as per http://aprs.gids.nl/nmea/#gsa was the reference as
+// the field numbers conveniently match our index.
static void
gpgsa_parse(char* ibuf)
{
- char fixauto;
- char fix;
int prn[12] = {0};
- int scn,cnt;
- float pdop=0,hdop=0,vdop=0;
- char* tok=0;
-
memset(prn,0xff,sizeof(prn));
- scn = sscanf(ibuf,"$%*2cGSA,%c,%c,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
- &fixauto, &fix,
- &prn[0],&prn[1],&prn[2],&prn[3],&prn[4],&prn[5],
- &prn[6],&prn[7],&prn[8],&prn[9],&prn[10],&prn[11]);
- if (scn < 2) {
- warning(MYNAME ": Short GSA sentence.\n");
- }
- /*
- sscanf has scanned all the leftmost elements
- we'll rescan by skipping 15 commas to the dops
- */
- tok = ibuf;
- for (cnt=0; (tok)&&(cnt<15); cnt++) {
- tok = strchr(tok,',');
- if (!tok) {
- break;
- }
- tok++;
+ QStringList fields = QString(ibuf).split(",", QString::KeepEmptyParts);
+ int nfields = fields.size();
+ // 0 = "GPGSA"
+ // 1 = Mode. Ignored
+ QChar fix;
+ if (nfields > 1) {
+ fix = fields[2][0];
}
- if (tok) {
- sscanf(tok,"%f,%f,%f",&pdop,&hdop,&vdop);
+ // 12 fields, index 3 through 14.
+ for (int cnt = 0; cnt <= 11; cnt++) {
+ if (nfields >= cnt + 2) prn[cnt] = fields[cnt + 3].toInt();
}
+ float pdop = 0, hdop = 0, vdop = 0;
+ if (nfields > 14) pdop = fields[15].toDouble();
+ if (nfields > 15) hdop = fields[16].toDouble();
+ if (nfields > 16) {
+ // Last one is special. The checksum isn't split out above.
+ fields[17].chop(3);
+ vdop = fields[17].toDouble();
+ }
if (curr_waypt) {
-
if (curr_waypt->fix!=fix_dgps) {
- if (fix=='3') {
- curr_waypt->fix=fix_3d;
- } else if (fix=='2') {
- curr_waypt->fix=fix_2d;
+ if (fix=='3') {
+ curr_waypt->fix = fix_3d;
+ } else if (fix=='2') {
+ curr_waypt->fix = fix_2d;
}
}
curr_waypt->hdop = hdop;
curr_waypt->vdop = vdop;
- if (curr_waypt->sat <= 0) {
- for (cnt=0; cnt<12; cnt++) {
- curr_waypt->sat += (prn[cnt]>0)?(1):(0);
+ if (curr_waypt->sat <= 0) {
+ for (int cnt = 0; cnt <= 11; cnt++) {
+ curr_waypt->sat += (prn[cnt] > 0) ? 1 : 0;
}
}
}
/*
* Since we oh-so-cleverly inserted points at the head,
* we can rip through the queue forward now to get our
- ` * handy-dandy reversing effect.
+ * handy-dandy reversing effect.
*/
trk_head = route_head_alloc();
track_add_head(trk_head);
Waypoint* wpt = (Waypoint*)elem;
wpt->creation_time += delta_tm;
- if ((prev != NULL) && (prev->creation_time > wpt->creation_time)) { /* go over midnight ? */
+ if ((prev != NULL) && (prev->creation_time > wpt->creation_time)) {
+ /* go over midnight ? */
delta_tm += SECONDS_PER_DAY;
wpt->creation_time += SECONDS_PER_DAY;
}
time_t prev;
queue* elem;
- tm.tm_hour = 23; /* last date found */
+ tm.tm_hour = 23; /* last date found */
tm.tm_min = 59;
tm.tm_sec = 59;
if (wpt->wpt_flags.fmt_use != 0) {
time_t dt;
- wpt->wpt_flags.fmt_use = 0; /* reset flag */
+ wpt->wpt_flags.fmt_use = 0; /* reset flag */
dt = (prev / SECONDS_PER_DAY) * SECONDS_PER_DAY;
wpt->creation_time += dt;
ck++;
sscanf(ck, "%2X", &ckcmp);
if (ckval != ckcmp) {
-#if 0
- printf("ckval %X, %X, %s\n", ckval, ckcmp, ck);
- printf("NMEA %s\n", tbuf);
-#endif
+ Warning() << "Invalid NMEA checksum. Computed " << ckval << " but found " << ckcmp << ". Ignoring sentence";
return;
}
/* GISTeq doesn't care about the checksum, but wants this prefixed, so
* we can write it with abandon.
- */
+ */
if (opt_gisteq) {
gbfprintf(file_out, "---,");
}
static void
nmea_wr_posn_deinit(void)
{
-// nmea_wr_deinit();
+// nmea_wr_deinit();
}
nmea_write,
NULL,
nmea_args,
- CET_CHARSET_ASCII, 0, /* CET-REVIEW */
+ CET_CHARSET_ASCII, 0, /* CET-REVIEW */
{
nmea_rd_posn_init, nmea_rd_posn, nmea_rd_deinit,
nmea_wr_posn_init, nmea_wr_posn, nmea_wr_posn_deinit